<?php

namespace Application\model;

use Cola\Exception;
use Cola\Model;

class BanModel extends Model
{

    public function ban($rows)
    {
        $rows['remark'] = (defined('PFORM_NAME') ? PFORM_NAME : '').'平台';
        return $this->publicBan($rows['target'] ?? '',$rows['type'],$rows);
    }

    public function unban($rows)
    {
        $rows['remark'] = (defined('PFORM_NAME') ? PFORM_NAME : '').'平台';
        return $this->publicUnBan($rows['target'] ?? '',$rows['type'],$rows);
    }
    public function handle($rows, $isUnban=false)
    {

        $banTime = 0;
        $account = '';
        $actor_id = 0;
        $channel = $this->model('channel');
        if ($rows['actor_id']) $actor_id = $rows['actor_id'];
        if ($rows['account']){
            $rows['channel_account'] =$rows['account'];
            $rows['account'] = $account = $channel->realAccount($rows['account']);
        }

        if (!$isUnban) {
            $rows['bantime'] = intval($rows['bantime'] ?? 0);//分钟
            $rows['bantime'] < 0 && $rows['bantime'] = 0;
        }
        //默认类型
        if(!isset($rows['type'])){
            if($actor_id){
                $rows['type'] = BAN_ACTOR;
            }else{
                $rows['type'] = BAN_ACCOUNT;
            }
        }
        if(($rows['actor_id'] ?? 0) && !($rows['sid'] ?? 0)){
            $accountInfo = $this->model('Account')->getAccountInfo($account ?? '' ,0,$rows['actor_id']);
            $rows['sid'] = $accountInfo['sid']  ?? 0;
        }
        //后台目标字段target
        $rows['target'] = $rows['type'] ==2 ? $account : ($actor_id ?: $account);
        return $this->{$isUnban ? 'unban' : 'ban'}($rows);


        $banAccount = false;
        // user存在 role_id、role_name不存在时 代表处理的是用户，对该用户下的所有角色都生效，server可能也不存在
        // 有account 是封/解封账号
        if ($rows['account'] && empty($rows['role_id']) && empty($rows['role_name']) ) {
            // 封帐号
            if ($rows['type'] === 3) $res = $this->banAccount($account, $banTime, $isUnban);
            // 禁言
            if ($rows['type'] === 1) $res = $this->banAccountChat($account, $banTime, $isUnban);
            $banAccount = true;
        }
        // role_id、role_name都存在或存在其一时 代表处理的是单一角色
        elseif ($rows['role_id'] || $rows['role_name'] ) {
            $actor = $rows['role_id'];
            if (empty($actor))$actor = $rows['role_name'];
            $res = $this->banActor($actor, $banTime, $rows['type'], $isUnban);
        }
        // 入库
        if ($res !== false){
            $rows['clear_chat'] = 1;
            $rows['cid'] = CID;
            $rows['remark'] = (defined('PFORM_NAME') ? PFORM_NAME : '').'平台';
            if ($isUnban) {
                // 封账号
                if ($banAccount) {
                    $where = "account = '{$account}'";
                } else {
                    // 封角色返回的是角色ID
                    $where = "actor_id = '{$res}'";
                }
                $res = $this->db('_backdb')->update(
                    ['unban_user'=>'接口', 'unban_dt'=>date('Y-m-d H:i:s'), 'status'=>2],
                    "type={$rows['type']} and $where and status=1",
                    'gm_ban'
                );
            } else {
                $rows['actor_name'] = $rows['role_name'];
                $rows['actor_id'] = $rows['role_id'];
                $rows['ban_user'] = '接口';
                $rows['ban_dt'] = date('Y-m-d H:i:s');
                $rows['status'] = 1;
                $rows['ban_time'] = round($banTime/60);
                if ($rows['account']) $rows['account'] = $account;
                if (empty($rows['sid'])) unset($rows['sid']);
                if (empty($rows['actor_id'])) unset($rows['actor_id']);
                if (empty($rows['actor_name'])) unset($rows['actor_name']);
                unset($rows['role_name'], $rows['role_id']);
                $res = $this->db('_backdb')->insert($rows, 'gm_ban');
            }
            if ($res) {
                return true;
            } else {
                $this->logfile("handle table error:".json_encode($rows));
                return false;
            }
        }else {
            return false;
        }
    }

    // 封/解封角色、禁言
    public function banActor($actor, $banTime, $type, $unban=false) {
        // 先去account表查询角色信息
        $accountInfo = $this->model('Account')->getAccountByActor($actor);
        if (empty($accountInfo)) {
            $this->logfile("empty actor:{$actor}");
            return false;
        }
        $server = $this->model('Server')->getServerBySid($accountInfo['sid']);
        if (empty($server)) {
            $this->logfile("empty server:{$accountInfo['sid']}");
            return false;
        }
        $command = '';
        $param = 'type=1&time='.$banTime;

        if ($unban) $param = 'type=2&time=1';

        switch ($type){
            case 1:
                $command = 'chatShield';
                break;
            case 3:
                $command = 'black';
                break;
        }
        $param .= '&player='.$accountInfo['actor_id'];
        $url = $server['ip'].':'.$server['port'];
        $res = serverApi($url, $command, $param);
        $this->logfile("url:$url/$command?{$param} res:".json_encode($res));
        $res = json_decode($res, true);
        // 入库
        if ($res['code']===1){
            return $accountInfo['actor_id'];
        } else {
            $this->logfile("api error:$url, $command, $param result:".json_encode($res));
            return false;
        }
    }

    public function banAccountChat($account, $banTime, $unban=false) {
        // 检查玩家账号是否正确
        $accountInfo = $this->model('Account')->getAccountByAccount($account);

        if (empty($accountInfo)) {
            $this->logfile("empty account:{$account}");
            return false;
        }
        $sids = [];
        foreach ($accountInfo as $item) {
            $sids[$item['sid']] = $item['actor_id'];
        }
        $sidStr = implode(',', array_keys($sids));
        $servers = $this->model('Server')->getServers("sid in ($sidStr)");
        if ($servers) {
            foreach ($servers as $server) {
                if (isset($sids[$server['sid']])){
                    $url = $server['ip'].':'.$server['port'];
                    $res = serverApi($url, 'chatShield', 'type=1&player='.$sids[$server['sid']].'&time='.$banTime);
                    $this->logfile("url:$url/chatShield?type=1&player={$sids[$server['sid']]}&time={$banTime} res:".json_encode($res));
                }
            }
        }

    }

    /**
     * 封帐号
     * @param $account
     * @param $banTime
     * @param $unban
     * @return bool
     * @throws Exception\DbException
     */
    public function banAccount($account, $banTime, $unban=false)
    {
        // 检查玩家账号是否正确
        $accountInfo = $this->model('Account')->getAccountByAccount($account);

        if (empty($accountInfo)) {
            $this->logfile("empty account:{$account}");
            return false;
        }
        // 修改account表
        $status = 0;
        if ($unban) $status = 1;
        $res = $this->db->update(['status'=>$status], "account='{$account}'", 'accounts');
        if ($res) {
            // 封号要通知服务端
            if (!$unban) {
                $sids = [];
                foreach ($accountInfo as $item) {
                    $sids[$item['sid']] = $item['actor_id'];
                }
                $sidStr = implode(',', array_keys($sids));
                $servers = $this->model('Server')->getServers("sid in ($sidStr)");
                if ($servers) {
                    foreach ($servers as $server) {
                        if (isset($sids[$server['sid']])){
                            $url = $server['ip'].':'.$server['port'];
                            $res = serverApi($url, 'black', 'type=3&player='.$sids[$server['sid']].'&time='.$banTime);
                            $this->logfile("url:$url/black?type=3&player={$sids[$server['sid']]}&time={$banTime} res:".json_encode($res));
                        }
                    }
                }
            }
            return true;
        }
        return false;
    }


    public function checkBanIp()
    {
        $ip = ip();
        $sql = "SELECT * FROM `gm_ban_ip` where status=1 and ip='$ip'";
        $res = $this->db->sql($sql);
        if ($res){
            logfile('LoginModel', "ip:$ip baned");
            return true;
        } else {
            return false;
        }
    }

    public function getBanTimeByIp($ip)
    {
        $sql = "SELECT * FROM `gm_ban` where status=1 and ip='$ip'";
        $res = $this->db('_backdb')->row($sql);
        return $res;
    }


    public function publicBan($target,$type,$rows=[])
    {
        $data = compact('target','type');
        $data['target'] = $target;
        $data['type'] = $type;
        $data = $data + $rows;
        logfile('BanModel', 'publicBan::'.json_encode($data));
        $url = BACKEN_URL.'/api/ban?'.http_build_query($data);
        logfile('BanModel', $url);
        $res = curl($url,$data,1,['Authorization: loginpay']);
        try{
            $return = json_decode($res, true);
            if(!$return || ($return['code']!==20000)){
                logfile('BanModel', $res);
            }
        }catch (\Throwable $exception){
            $return = [];
            logfile('BanModel', 'error:'.$exception->getMessage());
        }
        APP_DEV==2 && logfile('BanModel', $res);
        return compact('return');

    }

    public function publicUnBan($target,$type,$rows=[])
    {
        $sql = "SELECT * FROM `gm_ban`";
        $data = $this->db('_backdb')->row($sql) ?? [];
        $data['target'] = $target;
        $data['type'] = $type;
        $data['id'] = -1;
        $data = $data + $rows;
        logfile('BanModel ', 'publicUnBan::'.json_encode($data));
        $url = BACKEN_URL.'/api/unban?'.http_build_query($data);
        logfile('BanModel', $url);
        $res = curl($url,$data,1,['Authorization: loginpay']);
        try{
            $return = json_decode($res, true);
            if(!$return || ($return['code']!==20000)){
                logfile('BanModel', $res);
            }
        }catch (\Throwable $exception){
            $return = [];
            logfile('BanModel', 'error:'.$exception->getMessage());
        }
        APP_DEV==2 && logfile('BanModel', $res);
        return compact('return');

    }

}